//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// Target Devices:
// Tool versions:
//
// Create Date:    2011-08-18 15:28
// Project Name:
// Description:
//     
// Dependencies:
//
// Revision: 1.0
// Revision 0.01 - File Created
//
//
//////////////////////////////////////////////////////////////////////////////////
`timescale 1ns/1ns
module lcd_rgb_buff
(
    input               clk,
    input               rst,

    // line buffer fifo 
    input [31:0]        in_fifo_rddata,
    output reg          in_fifo_rdreq,
    input               in_fifo_empty,
    input               in_fifo_alempty,

    //lcd output fifo
    output [7:0]        out_fifo_data_r,
    output [7:0]        out_fifo_data_g,
    output [7:0]        out_fifo_data_b,
    output              out_fifo_empty,
    output              out_fifo_alempty,
    input               out_fifo_rdreq
);

/********************************************************\
Parameter
\********************************************************/
localparam  U_DLY           = 1;

/********************************************************\
Signals
\********************************************************/

wire                fifo_alfull;
reg                 wr_data_valid;
reg [1:0]           wr_data_cnt;
reg [1:0]           rgb_cnt;
reg                 wr_done;

wire [7:0]          r_fifo_wrdata;
wire                r_fifo_wrreq;
wire                r_fifo_alfull;
wire                r_fifo_empty;
wire                r_fifo_alempty;

wire [7:0]          g_fifo_wrdata;
wire                g_fifo_wrreq;
wire                g_fifo_alfull;
wire                g_fifo_empty;
wire                g_fifo_alempty;

wire [7:0]          b_fifo_wrdata;
wire                b_fifo_wrreq;
wire                b_fifo_alfull;
wire                b_fifo_empty;
wire                b_fifo_alempty;

reg                 in_fifo_rdreq_dly1;
reg                 fifo_wrreq;
reg [31:0]          in_fifo_shift_reg;

/********************************************************\
main code
\********************************************************/

assign out_fifo_alempty = r_fifo_alempty | g_fifo_alempty | b_fifo_alempty;
assign out_fifo_empty = r_fifo_empty | g_fifo_empty | b_fifo_empty;
assign fifo_alfull = r_fifo_alfull | g_fifo_alfull | b_fifo_alfull;
assign r_fifo_wrreq = fifo_wrreq & (rgb_cnt==2'h0);
assign g_fifo_wrreq = fifo_wrreq & (rgb_cnt==2'h1);
assign b_fifo_wrreq = fifo_wrreq & (rgb_cnt==2'h2);
assign r_fifo_wrdata = in_fifo_shift_reg[7:0];
assign g_fifo_wrdata = in_fifo_shift_reg[7:0];
assign b_fifo_wrdata = in_fifo_shift_reg[7:0];

always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
        in_fifo_rdreq <= 1'b0;
    end
    else if(~fifo_alfull & wr_done & (~in_fifo_rdreq))
    begin
        in_fifo_rdreq   <= #U_DLY ~in_fifo_empty;
    end
    else
    begin
        in_fifo_rdreq   <= #U_DLY 1'b0;
    end 
end

always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
        in_fifo_shift_reg   <= 'h0;
    end
    else if(in_fifo_rdreq_dly1)
    begin
        in_fifo_shift_reg   <= #U_DLY in_fifo_rddata;
    end
    else if(fifo_wrreq)
    begin
        in_fifo_shift_reg   <= #U_DLY {8'h0,in_fifo_shift_reg[31:8]};
    end 
end

always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
        in_fifo_rdreq_dly1  <= 1'b0;
    end
    else
    begin
        in_fifo_rdreq_dly1  <= #U_DLY in_fifo_rdreq;
    end
end

always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
        fifo_wrreq  <= 1'b0;
    end
    else if(~fifo_wrreq & wr_data_valid)
    begin
        fifo_wrreq  <= #U_DLY ~fifo_alfull;
    end
    else
    begin
        fifo_wrreq  <= #U_DLY 1'b0;
    end 
end

always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
        rgb_cnt <= 'h0;
    end
    else if(fifo_wrreq & (rgb_cnt==2'h2))
    begin
        rgb_cnt <= #U_DLY 'h0;
    end
    else if(fifo_wrreq)
    begin
        rgb_cnt <= #U_DLY rgb_cnt + 1'b1;
    end
end

always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
        wr_data_cnt <= 'h0;
    end
    else if(fifo_wrreq)
    begin
        wr_data_cnt <= #U_DLY wr_data_cnt + 1'b1;
    end
end

always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
        wr_data_cnt <= 'h0;
    end
    else if(fifo_wrreq)
    begin
        wr_data_cnt <= #U_DLY wr_data_cnt + 1'b1;
    end
end

always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
        wr_data_valid   <= 1'b0;
    end
    else if(in_fifo_rdreq_dly1)
    begin
        wr_data_valid   <= #U_DLY 1'b1;
    end
    else if(fifo_wrreq & (wr_data_cnt==2'd3))
    begin
        wr_data_valid   <= #U_DLY 1'b0;
    end 
end

always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
        wr_done <= 1'b1;
    end
    else if(in_fifo_rdreq)
    begin
        wr_done <= #U_DLY 1'b0;
    end
    else if(fifo_wrreq)
    begin
        wr_done   <= #U_DLY (wr_data_cnt==2'd3);
    end 
end

// instance
SCFIFO_128x8_FWFT fifo_r(
  .clk          (clk),
  .rst          (rst),
  .din          (r_fifo_wrdata),
  .wr_en        (r_fifo_wrreq),
  .rd_en        (out_fifo_rdreq),
  .dout         (out_fifo_data_r),
  .full         (),
  .almost_full  (r_fifo_alfull),
  .empty        (r_fifo_empty),
  .almost_empty (r_fifo_alempty)
);

SCFIFO_128x8_FWFT fifo_g(
  .clk          (clk),
  .rst          (rst),
  .din          (g_fifo_wrdata),
  .wr_en        (g_fifo_wrreq),
  .rd_en        (out_fifo_rdreq),
  .dout         (out_fifo_data_g),
  .full         (),
  .almost_full  (g_fifo_alfull),
  .empty        (g_fifo_empty),
  .almost_empty (g_fifo_alempty)
);

SCFIFO_128x8_FWFT fifo_b(
  .clk          (clk),
  .rst          (rst),
  .din          (b_fifo_wrdata),
  .wr_en        (b_fifo_wrreq),
  .rd_en        (out_fifo_rdreq),
  .dout         (out_fifo_data_b),
  .full         (),
  .almost_full  (b_fifo_alfull),
  .empty        (b_fifo_empty),
  .almost_empty (b_fifo_alempty)
);

endmodule
